package burubaka.service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

import net.arnx.jsonic.JSON;

import org.slim3.datastore.Datastore;

import burubaka.common.BurubakaUtil;
import burubaka.common.KeibaNiftyUtil;
import burubaka.common.NetkeibaUtil;
import burubaka.meta.ResultHorseMeta;
import burubaka.model.RaceInfo;
import burubaka.model.ResultHorse;

import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.Transaction;

/**
 * @author tk
 * 
 */
public class ResultHorseService {

	private static final Logger log = Logger.getLogger(ResultHorseService.class.getName());

	private ResultHorseMeta meta = new ResultHorseMeta();

	/**
	 * 着順馬柱を取得する
	 * 
	 * @param key
	 * @return ResultHorseList
	 */
	public List<ResultHorse> findByResultHorseKey(Key key) {
		if (key == null) {
			return new ArrayList<ResultHorse>();
		}
		return Datastore.query(meta, key).sort(meta.finishPoint.asc).asList();
	}

	/**
	 * 着順馬柱を取得する
	 * 
	 * @param key
	 * @param limit
	 * @return ResultHorseList
	 */
	public List<ResultHorse> findByResultHorseKey(Key key, int limit) {
		if (key == null) {
			return new ArrayList<ResultHorse>();
		}
		return Datastore.query(meta, key).sort(meta.finishPoint.asc).limit(limit).asList();
	}

	/**
	 * URLテキストを取得する
	 * 
	 * @param raceInfo
	 * @return URLText
	 * @throws Exception
	 */
	public static String getURLText(RaceInfo raceInfo) throws Exception {
		if (BurubakaUtil.isLocal(raceInfo.getDistrictClass())) {
			return NetkeibaUtil.getResultURLText(raceInfo);
		}
		return KeibaNiftyUtil.getResultURLText(raceInfo);
	}

	/**
	 * 着順馬柱を取得する
	 * 
	 * @param raceInfo
	 * @return ResultHorseList
	 * @throws Exception
	 */
	public List<ResultHorse> getResultHorseList(RaceInfo raceInfo) throws Exception {

		List<ResultHorse> list = this.findByResultHorseKey(raceInfo.getKey());
		if (BurubakaUtil.isNotEmpty(list)) {
			return list;
		}

		return getResultHorseListByOuter(raceInfo);
	}

	/**
	 * 外部サイトから着順馬柱を取得する
	 * 
	 * @param raceInfo
	 * @return ResultHorseList
	 * @throws Exception
	 */
	public List<ResultHorse> getResultHorseListByOuter(RaceInfo raceInfo) throws Exception {

		String text = getURLText(raceInfo);
		if (BurubakaUtil.isLocal(raceInfo.getDistrictClass())) {
			return getLoclaRaceCardHorseList(text);
		}

		return getResultHorseList(text);
	}

	/**
	 * 中央の着順馬柱を取得する
	 * 
	 * @param text
	 * @return ResultHorseList
	 */
	private List<ResultHorse> getResultHorseList(String text) {

		String dataTbl = BurubakaUtil.substring("<div class=\"dataTbl\">", "</div>", text);

		if (dataTbl == null) {
			return new ArrayList<ResultHorse>();
		}

		ArrayList<String> finishPoint = KeibaNiftyUtil.getFinishPointList(dataTbl);
		log.info(finishPoint.toString());

		ArrayList<String> waku = KeibaNiftyUtil.getWakuList(dataTbl);
		log.info(waku.toString());

		ArrayList<String> horseNo = KeibaNiftyUtil.getHorseNoList(dataTbl);
		log.info(horseNo.toString());

		ArrayList<String> horseNamesA = KeibaNiftyUtil.getHorseNameAList(dataTbl);
		log.info(horseNamesA.toString());

		ArrayList<String> horseNames = BurubakaUtil.removeATag(horseNamesA);
		log.info(horseNames.toString());

		ArrayList<String> sexAgeL = KeibaNiftyUtil.getSexAgeList(dataTbl);
		log.info(sexAgeL.toString());

		ArrayList<String> weight = KeibaNiftyUtil.getWeightList(dataTbl);
		log.info(weight.toString());

		ArrayList<String> jockeysA = KeibaNiftyUtil.getJockeyAList(dataTbl);
		log.info(jockeysA.toString());

		ArrayList<String> jockeys = BurubakaUtil.removeATag(jockeysA);
		log.info(jockeys.toString());

		return getResultHorseList(finishPoint, waku, horseNo, horseNames, horseNamesA, sexAgeL, weight, jockeys, null);
	}

	/**
	 * 地方の着順馬柱を取得する
	 * 
	 * @param text
	 * @return RaceCardHorseList
	 */
	private List<ResultHorse> getLoclaRaceCardHorseList(String text) {

		List<String> trList = NetkeibaUtil.getHorseInfoAreaList(text);
		if (trList == null) {
			return new ArrayList<ResultHorse>();
		}

		ArrayList<String> finishPoint = new ArrayList<String>();
		List<String> wakueNoL = new ArrayList<String>();
		List<String> horseNoL = new ArrayList<String>();
		List<String> horseNameAL = new ArrayList<String>();
		List<String> horseNameL = new ArrayList<String>();
		List<String> memos = new ArrayList<String>();
		List<String> sexAgeL = new ArrayList<String>();
		List<String> weightL = new ArrayList<String>();
		List<String> jockeyL = new ArrayList<String>();

		for (String trStr : trList) {
			finishPoint.add(NetkeibaUtil.getFinishPoint(trStr));
			wakueNoL.add(NetkeibaUtil.getWakuNo(trStr));
			List<String> tempL = NetkeibaUtil.getHorseInfo(trStr);
			horseNoL.add(tempL.get(0));
			String horseNameA = NetkeibaUtil.getHorseNameA(trStr);
			horseNameAL.add(horseNameA);
			String horseName = BurubakaUtil.removeATag(horseNameA);
			horseNameL.add(horseName);
			sexAgeL.add(tempL.get(1));
			weightL.add(tempL.get(2));
			String jockey = NetkeibaUtil.getJockeyA(trStr);
			jockey = BurubakaUtil.removeATag(jockey);
			jockeyL.add(jockey);
			memos.add("");
		}

		return getResultHorseList(finishPoint, wakueNoL, horseNoL, horseNameL, horseNameAL, sexAgeL, weightL, jockeyL,
				null);
	}

	/**
	 * 登録
	 * 
	 * @param input
	 * @param raceInfo
	 * @return boolean
	 */
	public boolean regist(Map<String, Object> input, RaceInfo raceInfo) {
		log.info(input.toString());
		ResultHorse[] rsh = JSON.decode((String) input.get("rsHorseL"), ResultHorse[].class);

		// Map<String, Object> map =
		// JSON.decode((String)input.get("json"),HashMap.class);
		// List<String> finishPoint = BurubakaUtil.getRequestArray(map,
		// "finishPoint");
		// List<String> horseNo = BurubakaUtil.getRequestArray(map, "horseNo");
		// List<String> horseNames = BurubakaUtil.getRequestArray(map,
		// "horseName");
		// List<String> sexAgeL = BurubakaUtil.getRequestArray(map, "sexAge");
		// List<String> weight = BurubakaUtil.getRequestArray(map, "weight");
		// List<String> jockeys = BurubakaUtil.getRequestArray(map, "jockey");

		Transaction tx = Datastore.beginTransaction();
		List<Key> old = BurubakaUtil.gatKeyList(meta, raceInfo.getKey());
		Datastore.delete(old);

		// List<ResultHorse> list =
		// ResultHorseService.getResultHorseList(finishPoint,horseNo,horseNames,null,sexAgeL,weight,jockeys,raceInfo.getKey());

		List<ResultHorse> list = ResultHorseService.getResultHorseList(rsh, raceInfo.getKey());
		Datastore.put(list);
		tx.commit();
		return true;
	}

	/**
	 * 登録
	 * 
	 * @param list
	 * @param raceInfo
	 * @return boolean
	 */
	public boolean regist(List<ResultHorse> list, RaceInfo raceInfo) {

		Transaction tx = Datastore.beginTransaction();
		Key key = raceInfo.getKey();
		List<Key> old = BurubakaUtil.gatKeyList(meta, key);
		Datastore.delete(old);

		for (ResultHorse rsh : list) {
			if (key != null) {
				Key childKey = Datastore.allocateId(key, ResultHorse.class);
				rsh.setKey(childKey);
			}
		}

		Datastore.put(list);
		tx.commit();
		return true;
	}

	/**
	 * 着順馬柱を取得する
	 * 
	 * @param finishPoint
	 * @param horseNo
	 * @param horseNames
	 * @param horseNamesA
	 * @param sexAgeL
	 * @param weight
	 * @param jockeys
	 * @param key
	 * @return ResultHorseList
	 */
	private List<ResultHorse> getResultHorseList(List<String> finishPoint, List<String> waku, List<String> horseNo,
			List<String> horseNames, List<String> horseNamesA, List<String> sexAgeL, List<String> weight,
			List<String> jockeys, Key key) {
		List<ResultHorse> list = new ArrayList<ResultHorse>();
		for (int i = 0; i < horseNames.size(); i++) {
			ResultHorse rsh = new ResultHorse();
			rsh.setHorseName(horseNames.get(i));
			if (BurubakaUtil.isNotEmpty(finishPoint, i)) {
				rsh.setFinishPoint(finishPoint.get(i));
			}
			if (BurubakaUtil.isNotEmpty(waku, i)) {
				rsh.setWaku(waku.get(i));
			}
			if (BurubakaUtil.isNotEmpty(horseNo, i)) {
				rsh.setHorseNo(horseNo.get(i));
			}
			if (BurubakaUtil.isNotEmpty(horseNamesA, i)) {
				rsh.setHorseNameA(horseNamesA.get(i));
			}
			if (BurubakaUtil.isNotEmpty(horseNames, i)) {
				rsh.setHorseName(horseNames.get(i));
			}
			if (BurubakaUtil.isNotEmpty(sexAgeL, i)) {
				rsh.setSexAge(sexAgeL.get(i));
			}
			if (BurubakaUtil.isNotEmpty(weight, i)) {
				rsh.setWeight(weight.get(i));
			}
			if (BurubakaUtil.isNotEmpty(jockeys, i)) {
				rsh.setJockey(jockeys.get(i));
			}
			if (key != null) {
				Key childKey = Datastore.allocateId(key, ResultHorse.class);
				rsh.setKey(childKey);
			}
			list.add(rsh);
		}
		return list;
	}

	/**
	 * 着順馬柱を取得する
	 * 
	 * @param rsHorses
	 * @param key
	 * @return ResultHorseList
	 */
	public static List<ResultHorse> getResultHorseList(ResultHorse[] rsHorses, Key key) {
		List<ResultHorse> list = new ArrayList<ResultHorse>();
		for (ResultHorse rsh : rsHorses) {
			if (key != null) {
				Key childKey = Datastore.allocateId(key, ResultHorse.class);
				rsh.setKey(childKey);
			}
			list.add(rsh);
		}
		return list;
	}

}
